/*
 *   Copyright 2012-present OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

// Packages
import axios from 'axios';
import { push } from 'connected-react-router';
import qs from 'qs';
import Cookies from 'universal-cookie';
import jwt_decode from 'jwt-decode';
import { Intent, Position } from '@blueprintjs/core';

// Actions
import { getLicense } from './licenseActions';
import { getDatasources } from './datasourcesActions';
import { clearErrors } from './errorActions';

// Utils
import { Saiku, setAuthToken, Settings } from '../utils';

// Types
import {
  LOADING_SESSION,
  SET_CURRENT_SESSION,
  GET_ERRORS,
  RESET_STATE
} from './types';

const cookies = new Cookies();
const { COOKIE_NAME } = Settings;

export const checkSession = () => dispatch => {
  axios
    .get(`${Settings.REST_URL}/session`)
    .then(res => {
      const { data } = res;
      const { sessionid } = data;

      if (data === null || sessionid === undefined) {
        dispatch(doLogout());
      } else {
        dispatch(setCurrentSession(data));
        dispatch(getLicense());
        dispatch(getDatasources());
      }
    })
    .catch(error =>
      Saiku.axiosHandleErrors(
        'actions → sessionActions.js → checkSession()',
        error
      )
    );
};

export const doLogin = (username, password) => dispatch => {
  const loginData = {
    username,
    password
  };

  dispatch(loadingSession(true));

  axios
    .post(`${Settings.REST_URL}/session`, qs.stringify(loginData), {
      headers: {
        'content-type': 'application/x-www-form-urlencoded'
      }
    })
    .then(res => {
      const { data } = res;
      const { access_token } = data;

      if (access_token) {
        const decoded = jwt_decode(access_token);

        cookies.set(COOKIE_NAME, access_token, {
          path: '/',
          expires: Settings.getCookieExpires(decoded.exp)
        });

        // Set token to Auth header
        setAuthToken(access_token);
      }

      dispatch(loadingSession(false));
      dispatch(clearErrors());
      dispatch(checkSession());
    })
    .catch(error => {
      if (error.response && error.response.data) {
        const errorMsg = error.response.data.msg || error.response.data;

        dispatch(loadingSession(false));
        dispatch({
          type: GET_ERRORS,
          payload: errorMsg
        });
      }

      Saiku.axiosHandleErrors('actions → sessionActions.js → doLogin()', error);
    });
};

export const doLogout = (forceLogout = false) => dispatch => {
  axios
    .delete(`${Settings.REST_URL}/session`)
    .then(res => {
      dispatch(resetState());

      if (cookies.get(COOKIE_NAME)) {
        cookies.remove(COOKIE_NAME);
      }

      // Remove auth header for future requests
      setAuthToken(false);

      if (forceLogout) {
        Saiku.toasts(Position.TOP_RIGHT).show({
          icon: 'hand',
          intent: Intent.WARNING,
          message: 'Goodbye!'
        });
      }

      // Redirect to login page
      dispatch(push('/'));
    })
    .catch(error =>
      Saiku.axiosHandleErrors('actions → sessionActions.js → doLogout()', error)
    );
};

export const setCurrentSession = session => {
  return {
    type: SET_CURRENT_SESSION,
    payload: session
  };
};

export const loadingSession = (isLoading = true) => {
  return {
    type: LOADING_SESSION,
    payload: isLoading
  };
};

export const resetState = () => {
  return {
    type: RESET_STATE
  };
};
